#pragma once
#include "EventLoop.h"
#include "Acceptor.h"
#include "Connection.h"
#include "ThreadPool.h"

#include <map>
#include <memory>
#include <mutex>

class TcpServer
{
private:
    std::unique_ptr<EventLoop> m_mainloop;
    std::vector<std::unique_ptr<EventLoop>> m_subloops;

    Acceptor m_acceptor;
    std::map<int, ConnectionPtr> m_conns;

    int m_thread_num;
    ThreadPool m_threadpoll;
    std::mutex m_mutex;

    std::function<void(ConnectionPtr)> m_new_connection_callback;
    std::function<void(ConnectionPtr)> m_close_connection_callback;
    std::function<void(ConnectionPtr)> m_error_connection_callback;
    std::function<void(ConnectionPtr, std::string &)> m_on_message_callback;
    std::function<void(ConnectionPtr)> m_send_complete_callback;
    std::function<void(EventLoop *)> m_epoll_timeout_callback;

public:
    TcpServer(const char *ip, uint16_t port,int thread_num=3);
    ~TcpServer();

    void start();
    void new_connection(std::unique_ptr<Socket> clientsock);
    void close_connection(ConnectionPtr conn);
    void error_connection(ConnectionPtr conn);
    void on_message(ConnectionPtr conn, std::string &message);
    void send_complete(ConnectionPtr conn);
    void epoll_timeout(EventLoop *loop);

    void set_new_connection_callback(std::function<void(ConnectionPtr)> fn);
    void set_close_connection_callback(std::function<void(ConnectionPtr)> fn);
    void set_error_connection_callback(std::function<void(ConnectionPtr)> fn);
    void set_on_message_callback(std::function<void(ConnectionPtr, std::string &)> fn);
    void set_send_complete_callback(std::function<void(ConnectionPtr)> fn);
    void set_epoll_timeout_callback(std::function<void(EventLoop *)> fn);

    void remove_connection(int fd);

    void stop();
};